package com.zerui.manager.device.gatewayimpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zerui.manager.device.Device;
import com.zerui.manager.device.convertor.DeviceConvert;
import com.zerui.manager.device.custom.DeviceCustom;
import com.zerui.manager.device.entity.DeviceDo;
import com.zerui.manager.device.gateway.DeviceGateWay;
import com.zerui.manager.device.mapper.DeviceMapper;
import com.zerui.manager.feign.handler.DeviceFeignHandler;
import com.zerui.manager.feign.request.DeviceActionExecuteRequest;
import com.zerui.manager.icc.strategy.CommandStrategy;
import com.zerui.manager.icc.strategy.ICCCommandHandler;
import com.zerui.manager.web.cmd.DeviceOperateDoorCmd;
import com.zerui.manager.web.enums.DeviceAccessStatusEnum;
import com.zerui.manager.web.enums.DeviceOperateEnum;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.Time;
import java.util.*;

/**
 * @Author wh
 * @create_time 2023-08-23 15:28
 */
@Component
public class DeviceGateWayImpl implements DeviceGateWay {

    @Resource
    private DeviceMapper deviceMapper;
    @Resource
    private DeviceFeignHandler deviceFeignHandler;
    @Resource
    private ICCCommandHandler iccCommandHandler;

    @Override
    public List<Device> selectByDeviceIds(Set<Long> deviceList) {
        LambdaQueryWrapper<DeviceDo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(DeviceDo::getDeviceId,deviceList);
        List<DeviceDo> deviceDos = deviceMapper.selectList(queryWrapper);
        return DeviceConvert.INSTANCE.convertDeviceDosToDevices(deviceDos);
    }

    @Override
    public List<DeviceCustom> selectByDeviceIds2(Set<Long> deviceIds) {
        return deviceMapper.selectByDeviceIds2(deviceIds);
    }

    @Override
    public Device getByDeviceId(Long id) {
        LambdaQueryWrapper<DeviceDo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DeviceDo::getDeviceId,id);
        DeviceDo deviceDo = deviceMapper.selectOne(queryWrapper);
        return DeviceConvert.INSTANCE.convertDeviceDoToDevice(deviceDo);
    }

    @Override
    public void update(Device device) {
        DeviceDo deviceDo = DeviceConvert.INSTANCE.convertDeviceToDeviceDo(device);
        deviceMapper.updateById(deviceDo);
    }

    @Override
    public void add(Device device) {
        DeviceDo deviceDo = DeviceConvert.INSTANCE.convertDeviceToDeviceDo(device);
        deviceMapper.insert(deviceDo);
    }

    @Override
    public void invokeIoTCommandBatch(DeviceOperateDoorCmd deviceOperateDoorCmd) {
        List<DeviceActionExecuteRequest> requests = new ArrayList<>();
        Set<Long> deviceIds = deviceOperateDoorCmd.getDeviceIds();
        String action = deviceOperateDoorCmd.getOperate();
        deviceIds.forEach(e-> requests.add(DeviceActionExecuteRequest.builder()
                .id(e.toString())
                .actions(createAction(action))
                .build()));
        deviceFeignHandler.batchActionExecute(requests);
    }

    @Override
    public void invokeICCCommandBatch(DeviceOperateDoorCmd deviceOperateDoorCmd) {
        CommandStrategy command = iccCommandHandler.getCommand(deviceOperateDoorCmd.getOperate());
        command.execute(deviceOperateDoorCmd);
    }

    @Override
    public void deleteById(Long deviceId) {
        LambdaQueryWrapper<DeviceDo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DeviceDo::getDeviceId,deviceId);
        DeviceDo deviceDo = deviceMapper.selectOne(queryWrapper);
        if(ObjectUtils.isNotEmpty(deviceDo)){
            deviceMapper.deleteById(deviceDo.getId());
        }
    }

	@Override
	public void updateByDeviceId(Device device) {
    	//通过设备id 修改设备相关配置
		DeviceDo deviceDo = DeviceConvert.INSTANCE.convertDeviceToDeviceDo(device);
		LambdaQueryWrapper<DeviceDo> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(DeviceDo::getDeviceId,device.getDeviceId());
		deviceMapper.update(deviceDo, queryWrapper);
	}

	@Override
    public void iotDeviceAutoOpenEnable(Device device) {
    	    //开始结束时间需要调用  远程feign 实现物联网关调用
			List<DeviceActionExecuteRequest> requests = new ArrayList<>();
			requests.add(DeviceActionExecuteRequest
					.builder()
					.id(device.getDeviceId().toString())
					.actions(createAction(DeviceAccessStatusEnum.getActionByCode(device.getTimedTaskStatus())))
					.build());
		    deviceFeignHandler.batchActionExecute(requests);
	}

    @Override
    public void iccDeviceAutoOpenEnable(Device device) {
        DeviceOperateDoorCmd doorCmd = new DeviceOperateDoorCmd();
        doorCmd.setDeviceIds(Collections.singleton(device.getDeviceId()));
        doorCmd.setOperate(device.getTimedTaskStatus().equals(DeviceAccessStatusEnum.OPEN.getCode())
                ? DeviceOperateEnum.NORMALLY_OPEN.getAction() : DeviceOperateEnum.NORMALLY_OFF.getAction());
        CommandStrategy command = iccCommandHandler.getCommand(doorCmd.getOperate());
        command.execute(doorCmd);
    }

    @Override
	public List<Device> selectDeviceCurfewTimeStart(Time startTime, Time endTime, Integer timeTaskStatus) {
		LambdaQueryWrapper<DeviceDo> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.le(DeviceDo::getStartTime,endTime)
				.ge(DeviceDo::getStartTime,startTime)
				.eq(DeviceDo::getTimedTaskStatus,timeTaskStatus);
		List<DeviceDo> deviceDos = deviceMapper.selectList(queryWrapper);
		return DeviceConvert.INSTANCE.convertDeviceDosToDevices(deviceDos);
	}

    @Override
    public List<DeviceCustom> selectDeviceCurfewTimeStart2(Time startTime, Time endTime, Integer accessStatus) {
        return deviceMapper.selectDeviceCurfewTimeStart(startTime, endTime, accessStatus);
    }

    @Override
	public List<Device> selectDeviceCurfewTimeEnd(Time startTime, Time endTime, Integer timeTaskStatus) {
		LambdaQueryWrapper<DeviceDo> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.le(DeviceDo::getEndTime,endTime)
				.ge(DeviceDo::getEndTime,startTime)
				.eq(DeviceDo::getTimedTaskStatus,timeTaskStatus);
		List<DeviceDo> deviceDos = deviceMapper.selectList(queryWrapper);
		return DeviceConvert.INSTANCE.convertDeviceDosToDevices(deviceDos);
	}

    @Override
    public List<DeviceCustom> selectDeviceCurfewTimeEnd2(Time startTime, Time endTime, Integer accessStatus) {
        return deviceMapper.selectDeviceCurfewTimeEnd(startTime, endTime, accessStatus);
    }

    private Map<String, Map<String, Object>> createAction(String action) {
        Map<String, Map<String, Object>> map = new HashMap<>();
        map.put(action,new HashMap<>());
        return map;
    }
}
